home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of Down Under Games
/
The Best of Down Under Games.iso
/
3dfx Screen Savers
/
Spaghetti
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-12
|
27KB
|
1,033 lines
// Spaghetti! Screen Saver
// by Matt Lee
// This program is a real hack-job. Only one file, lots of global variables, no
// header files, etc. I really don't know much about making a Windows C program,
// so this is the result. The final program works quite well, though.
// As for a conversion to a real MS screensaver, here's what it needs:
// * The global variables at the beginning of the file need to be stuffed with
// values from the registry at initialization.
// * Some sort of UI needs to be made that will create the registry entries and
// set the appropriate values.
// * The current keyboard control code needs to be deactivated. This keyboard
// control was used during development to play around with the different
// paramaters and appearances of the spaghetti.
// The algorithm is quite simple. The noodles are made of 90 degree pipe elbows
// that rotate at the joints. There's several types of endcaps, joints, and
// centers that can be selected to further change the appearance.
// Due to the unfinished nature of the GLQuake opengl32.dll, I had to hack in
// my own version of directional lighting. It's by default coming from the +z
// direction. There is a vector to change the light's direction, but I doubt
// my lighting code is robust and bug-free enough to handle other cases.
// I will most probably fix this code up at a later date; I just wanted to have
// something done for the competition.
// This program only works with the old opengl32.dll (the Voodoo Graphics only
// version, sized 391KB (400,896 bytes). That DLL should be included with the
// program. I have not tested this code with Zanshin's DLL yet.
// Enjoy the program, and send all comments to mattlee@mit.edu.
#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
CHAR szAppName[]="Spaghetti!";
HWND ghWnd;
HDC ghDC;
HGLRC ghRC;
LONG WINAPI MainWndProc (HWND, UINT, WPARAM, LPARAM);
BOOL bSetupPixelFormat(HDC);
GLvoid makeTorusChunk (GLfloat major, GLfloat minor);
GLvoid makecolors (int armcount, int shadestyle);
GLvoid makenoodles (void);
GLvoid makeSphere (void);
#define WIDTH 640
#define HEIGHT 480
//#define WIDTH 512
//#define HEIGHT 384
#define sqr(x) ((x)*(x))
#define PI 3.14159265459f
#define TEX_WIDTH 64
#define TEX_HEIGHT 64
#define NUM_TEXTURES 2
GLfloat PITCH_SPEED = 0.90f;
GLfloat toroid[20][20][3];
GLfloat sphere[20][20][3];
GLfloat snorm[20][20][3];
GLfloat legcolor[20][2][3];
GLfloat rspeeds[8];
GLvoid resize(GLsizei, GLsizei);
GLvoid initializeGL(GLsizei, GLsizei);
GLvoid drawScene(GLvoid);
GLfloat lard = 0.3;
GLfloat majrad = 1.0;
// spts - segments per toroid segment
// qpr - quads per ring
int spts = 4;
int qpr = 16;
int noodlecount = 3;
int armlengths [8];
int ndlmin = 5;
int ndldelta = 5;
int framecount = 0;
int capstyle = 0;
int centerstyle = 0;
int shadestyle = 0;
int bufstyle = 0;
int cycleaccum = 0;
int colorcycle = 0;
float cyclepitch = 0.0;
float cyclespeed = 0.05;
int jointstyle = 0;
int hackclose = 1;
struct mvect {
GLfloat x;
GLfloat y;
GLfloat z;
};
typedef struct mvect vec3d;
vec3d masterlight;
/* Windows code.
*
* The windows portion of this code was taken from an MSVC example.
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS wndclass;
/* Register the frame class */
wndclass.style = 0;
wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon (hInstance, szAppName);
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclass.lpszMenuName = szAppName;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
return FALSE;
/* Create the frame */
/* Use the WS_POPUP window style to bring up a window that is
* exactly WIDTHxHEIGHT.
*/
ghWnd = CreateWindow(szAppName, "OpenGL Screensaver 1",
WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0, 0, WIDTH, HEIGHT,
NULL, NULL, hInstance, NULL);
/* Make sure window was created */
if (!ghWnd)
return FALSE;
/* Show and update main window */
ShowWindow(ghWnd, nCmdShow);
UpdateWindow(ghWnd);
SetFocus (ghWnd);
/* Animation loop */
while (hackclose) {
/* Process all pending messages */
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE) {
if (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
return TRUE;
}
}
drawScene();
}
}
LONG WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LONG lRet = 1;
PAINTSTRUCT ps;
RECT rect;
LONG xpos = 0;
LONG ypos = 0;
switch (uMsg) {
case WM_CREATE:
ghDC = GetDC(hWnd);
if (!bSetupPixelFormat(ghDC))
PostQuitMessage (0);
ghRC = wglCreateContext(ghDC);
wglMakeCurrent(ghDC, ghRC);
GetClientRect(hWnd, &rect);
initializeGL(rect.right, rect.bottom);
break;
case WM_PAINT:
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_SIZE:
GetClientRect(hWnd, &rect);
resize(rect.right, rect.bottom);
break;
case WM_CLOSE:
if (ghRC)
wglDeleteContext(ghRC);
if (ghDC)
ReleaseDC(hWnd, ghDC);
ghRC = 0;
ghDC = 0;
DestroyWindow (hWnd);
break;
case WM_DESTROY:
if (ghRC)
wglDeleteContext(ghRC);
if (ghDC)
ReleaseDC(hWnd, ghDC);
PostQuitMessage (0);
break;
case WM_MOUSEMOVE:
// hackclose = 0;
break;
case WM_KEYDOWN:
// hackclose = 0;
// break;
switch (wParam) {
case VK_ESCAPE:
hackclose = 0;
break;
case VK_SPACE:
makecolors (noodlecount, shadestyle);
break;
case VK_LEFT:
if (majrad > 0.05)
majrad -= 0.05;
makeTorusChunk (majrad, lard);
break;
case VK_RIGHT:
if (majrad < 3.0)
majrad += 0.05;
makeTorusChunk (majrad, lard);
break;
case VK_UP:
if (lard < 1.5)
lard += 0.025;
makeTorusChunk (majrad, lard);
break;
case VK_DOWN:
if (lard >= 0.025)
lard -= 0.025;
makeTorusChunk (majrad, lard);
break;
case VK_HOME:
if (spts < 16)
spts++;
makeTorusChunk (majrad, lard);
makeSphere ();
break;
case VK_END:
if (spts > 4)
spts--;
makeTorusChunk (majrad, lard);
makeSphere ();
break;
case VK_INSERT:
if (qpr < 16)
qpr++;
makeTorusChunk (majrad, lard);
makeSphere ();
break;
case VK_DELETE:
if (qpr > 3)
qpr--;
makeTorusChunk (majrad, lard);
makeSphere ();
break;
case VK_PRIOR:
if (PITCH_SPEED < 5.0f)
PITCH_SPEED += 0.05f;
break;
case VK_NEXT:
if (PITCH_SPEED > 0.0f)
PITCH_SPEED -= 0.05f;
break;
case VK_ADD:
if (noodlecount < 8)
noodlecount++;
break;
case VK_SUBTRACT:
if (noodlecount > 1)
noodlecount--;
break;
case VK_NUMPAD8:
if (ndlmin < 20)
ndlmin++;
makenoodles (0);
break;
case VK_NUMPAD2:
if (ndlmin > 1)
ndlmin--;
makenoodles (0);
break;
case VK_NUMPAD6:
if (ndldelta < 5)
ndldelta++;
makenoodles (0);
break;
case VK_NUMPAD4:
if (ndldelta > 0)
ndldelta--;
makenoodles (0);
break;
case VK_F1:
jointstyle++;
if (jointstyle > 2)
jointstyle = 0;
break;
case VK_F2:
capstyle++;
if (capstyle > 2)
capstyle = 0;
break;
case VK_F3:
centerstyle++;
if (centerstyle > 2)
centerstyle = 0;
break;
case VK_F4:
shadestyle++;
if (shadestyle > 3)
shadestyle = 0;
break;
case VK_F5:
bufstyle++;
if (bufstyle > 1)
bufstyle = 0;
break;
default:
break;
}
default:
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
}
return lRet;
}
BOOL bSetupPixelFormat(HDC hdc)
{
PIXELFORMATDESCRIPTOR pfd, *ppfd;
int pixelformat;
ppfd = &pfd;
ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
ppfd->nVersion = 1;
ppfd->dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
ppfd->dwLayerMask = PFD_MAIN_PLANE;
ppfd->iPixelType = PFD_TYPE_RGBA;
ppfd->cColorBits = 16;
ppfd->cDepthBits = 16;
ppfd->cAccumBits = 0;
ppfd->cStencilBits = 0;
pixelformat = ChoosePixelFormat(hdc, ppfd);
if ((pixelformat = ChoosePixelFormat(hdc, ppfd)) == 0) {
MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
return FALSE;
}
if (pfd.dwFlags & PFD_NEED_PALETTE) {
MessageBox(NULL, "Needs palette", "Error", MB_OK);
return FALSE;
}
if (SetPixelFormat(hdc, pixelformat, ppfd) == FALSE) {
MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
return FALSE;
}
return TRUE;
}
/* OpenGL code */
GLvoid resize( GLsizei width, GLsizei height )
{
GLfloat aspect;
glViewport(0, 0, width, height);
aspect = (GLfloat)width/(GLfloat)height;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, aspect, 3.0, 200.0);
glMatrixMode(GL_MODELVIEW);
}
GLfloat frandom ()
{
return (((GLfloat) (rand () % 100)) / 100.0f);
}
GLvoid makecolors (int armcount, int style) {
int i;
for (i = 0; i < 20; i++) {
legcolor [i][0][0] = 1.0 * frandom ();
legcolor [i][0][1] = 1.0 * frandom ();
legcolor [i][0][2] = 1.0 * frandom ();
legcolor [i][1][0] = 0.6 * frandom ();
legcolor [i][1][1] = 0.7 * frandom ();
legcolor [i][1][2] = 0.3 * frandom ();
}
}
GLvoid cyclecolors (float pitch) {
int i;
for (i = 0; i < 20; i++) {
legcolor [i][0][0] = 1.0 * sin (pitch / 10 + i + 0.010 * rspeeds [(int)pitch % 8]);
legcolor [i][0][1] = 1.0 * cos (pitch / 12 + i + 0.010 * rspeeds [((int)pitch + 1) % 8]);
legcolor [i][0][2] = 1.0 * sin (pitch / 15 + i + 0.010 * rspeeds [((int)pitch + 3) % 8]);
legcolor [i][1][0] = 0.6 * cos (pitch / 17 + i + 0.015 * rspeeds [((int)pitch + 6) % 8]);
legcolor [i][1][1] = 0.7 * sin (pitch / 14 + i + 0.013 * rspeeds [((int)pitch + 2) % 8]);
legcolor [i][1][2] = 0.3 * cos (pitch / 20 + i + 0.018 * rspeeds [((int)pitch + 4) % 8]);
}
}
GLvoid makenoodles (int mode) {
int i;
for (i = 0; i < 8; i++) {
if (mode == 1)
rspeeds [i] = frandom () + 0.5;
if (ndldelta == 0)
armlengths [i] = ndlmin;
else
armlengths [i] = (rand () % ndldelta) + ndlmin;
}
}
GLvoid initializeGL(GLsizei width, GLsizei height)
{
GLfloat aspect;
int i;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POLYGON_SMOOTH);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glMatrixMode(GL_PROJECTION);
aspect = (GLfloat)width/(GLfloat)height;
gluPerspective(45.0, aspect, 3.0, 200.0);
glMatrixMode(GL_MODELVIEW);
makeTorusChunk (majrad, lard);
makeSphere ();
srand( (unsigned)time( NULL ) );
makecolors (20, shadestyle);
makenoodles (1);
masterlight.x = 0.0;
masterlight.y = 0.0;
masterlight.z = 1.0;
}
GLint random ()
{
return ((rand () % 100) - 50);
}
GLvoid drawTetra (GLfloat alpha) {
glBegin (GL_TRIANGLE_FAN);
glColor4f (1.0f, 0.0f, 0.0f, alpha);
glVertex3f (0.0f, 1.0f, 0.0f);
glColor4f (1.0f, 1.0f, 0.0f, alpha);
glVertex3f (0.0f, -0.732f, 1.0f);
glColor4f (0.0f, 1.0f, 0.0f, alpha);
glVertex3f (1.0f, -0.732f, -0.732f);
glColor4f (0.0f, 0.0f, 1.0f, alpha);
glVertex3f (-1.0f, -0.732f, -0.732f);
glColor4f (1.0f, 1.0f, 0.0f, alpha);
glVertex3f (0.0f, -0.732f, 1.0f);
glEnd ();
glBegin (GL_TRIANGLES);
glColor4f (1.0f, 1.0f, 0.0f, alpha);
glVertex3f (0.0f, -0.732f, 1.0f);
glColor4f (0.0f, 1.0f, 0.0f, alpha);
glVertex3f (1.0f, -0.732f, -0.732f);
glColor4f (0.0f, 0.0f, 1.0f, alpha);
glVertex3f (-1.0f, -0.732f, -0.732f);
glEnd ();
}
float atan2fix (float a, float b) {
if ((a == 0.0) && (b == 0.0))
return (0.0);
else
return (atan2 (a, b));
}
vec3d vecrotate (vec3d vect, GLfloat angle, int a, int b, int c) {
vec3d t;
float theta;
float rad;
t.x = vect.x;
t.y = vect.y;
t.z = vect.z;
angle *= (PI / 180);
if (a == 1) {
t.x = vect.x;
theta = atan2fix (vect.y, vect.z);
if (theta < 0)
theta += (2 * PI);
theta += angle;
rad = sqrt (vect.y * vect.y + vect.z * vect.z);
t.y = rad * sin (theta);
t.z = rad * cos (theta);
} else if (b == 1) {
t.y = vect.y;
theta = atan2fix (-vect.z, vect.x);
if (theta < 0)
theta += (2 * PI);
theta += angle;
rad = sqrt (vect.z * vect.z + vect.x * vect.x);
t.z = rad * sin (theta);
t.x = rad * cos (theta);
} else if (c == 1) {
t.z = vect.z;
theta = atan2fix ((double)vect.y, (double)vect.x);
if (theta < 0)
theta += (2 * PI);
theta += angle;
rad = sqrt (vect.y * vect.y + vect.x * vect.x);
t.x = rad * sin (theta);
t.y = rad * cos (theta);
}
return (t);
}
vec3d vmult (GLfloat scalar, vec3d vect) {
vec3d t;
t.x = vect.x * scalar;
t.y = vect.y * scalar;
t.z = vect.z * scalar;
return (t);
}
vec3d vadd (vec3d a, vec3d b) {
vec3d temp;
temp.x = a.x + b.x;
temp.y = a.y + b.y;
temp.z = a.z + b.z;
return (temp);
}
vec3d vclear (GLvoid) {
vec3d t;
t.x = 0.0;
t.y = 0.0;
t.z = 0.0;
return (t);
}
GLvoid vset (int tsegment, int tvert, vec3d input) {
toroid [tsegment][tvert][0] = input.x;
toroid [tsegment][tvert][1] = input.y;
toroid [tsegment][tvert][2] = input.z;
}
GLvoid nset (int tsegment, int tvert, vec3d input) {
snorm [tsegment][tvert][0] = input.x;
snorm [tsegment][tvert][1] = input.y;
snorm [tsegment][tvert][2] = input.z;
}
GLvoid vfix (int tsegment) {
toroid [tsegment][qpr][0] = toroid [tsegment][0][0];
toroid [tsegment][qpr][1] = toroid [tsegment][0][1];
toroid [tsegment][qpr][2] = toroid [tsegment][0][2];
}
GLvoid sset (int ring, int vert, vec3d input) {
sphere [ring][vert][0] = input.x;
sphere [ring][vert][1] = input.y;
sphere [ring][vert][2] = input.z;
}
GLvoid makeTorusChunk (GLfloat major, GLfloat minor) {
int i, j;
GLfloat mjtheta = 0.0;
GLfloat mntheta = 0.0;
GLfloat mjdelta = ((PI * 0.5) / spts);
GLfloat mndelta = ((PI * 2) / qpr);
vec3d majorad;
vec3d minorxz;
vec3d minory;
vec3d temp;
vec3d vofs;
vec3d n;
vofs = vclear ();
vofs.x = -major;
minory.x = 0.0;
minory.z = 0.0;
minory.y = -1.0;
majorad.y = 0.0;
minorxz.y = 0.0;
for (mjtheta = 0.0, i = 0; i <= spts; mjtheta += mjdelta, i++) {
majorad.x = cos (mjtheta);
majorad.z = sin (mjtheta);
minorxz.x = cos (mjtheta);
minorxz.z = sin (mjtheta);
majorad = vmult (major, majorad);
for (mntheta = 0.0, j = 0; j < qpr; mntheta += mndelta, j++) {
temp = vclear ();
temp = vadd (vmult (cos (mntheta) * minor, minory),
vmult (sin (mntheta) * minor, minorxz));
n = vmult (1 / minor, temp);
nset (i, j, n);
temp = vadd (temp, majorad);
temp = vadd (temp, vofs);
vset (i, j, temp);
}
vfix (i);
}
}
GLvoid makeSphere (void) {
GLfloat theta = 0.0;
GLfloat phi = 0.0;
GLfloat dtheta = (2.0 * PI) / (GLfloat)qpr;
GLfloat dphi = (PI / 2.0) / (GLfloat)spts;
vec3d r;
int i, j;
for (i = 0, phi = 0.0; i <= spts; i++, phi += dphi) {
r.y = sin (phi);
for (j = 0, theta = 0.0; j < qpr; j++, theta += dtheta) {
r.x = cos (phi) * cos (theta);
r.z = cos (phi) * sin (theta);
sset (i, j, r);
}
}
}
GLvoid drawAxes (void) {
glBegin (GL_TRIANGLE_FAN);
glColor3f (1.0, 0.0, 0.0);
glVertex3f (1.0, 0.0, 0.0);
glVertex3f (0.0, 0.05, 0.0);
glVertex3f (0.0, 0.0, 0.05);
glVertex3f (0.0, 0.0, 0.0);
glVertex3f (0.0, 0.05, 0.0);
glEnd ();
glBegin (GL_TRIANGLE_FAN);
glColor3f (0.0, 1.0, 0.0);
glVertex3f (0.0, 1.0, 0.0);
glVertex3f (0.05, 0.0, 0.0);
glVertex3f (0.0, 0.0, 0.05);
glVertex3f (0.0, 0.0, 0.0);
glVertex3f (0.05, 0.0, 0.0);
glEnd ();
glBegin (GL_TRIANGLE_FAN);
glColor3f (0.0, 0.0, 1.0);
glVertex3f (0.0, 0.0, 1.0);
glVertex3f (0.05, 0.0, 0.0);
glVertex3f (0.0, 0.05, 0.0);
glVertex3f (0.0, 0.0, 0.0);
glVertex3f (0.05, 0.0, 0.0);
glEnd ();
}
GLvoid limbcolor (int armnum, int link, int head, GLfloat adder) {
switch (shadestyle) {
case 0: glColor3f (legcolor [armnum][0][0] * adder, legcolor [armnum][0][1] * adder,
legcolor [armnum][0][2] * adder);
break;
case 1: glColor3f (legcolor [armnum][head][0] * adder,
legcolor [armnum][head][1] * adder,
legcolor [armnum][head][2] * adder);
break;
case 2: if (rand () < 16384) head = !head;
glColor3f (legcolor [armnum][head][0] * adder,
legcolor [armnum][head][1] * adder,
legcolor [armnum][head][2] * adder);
break;
case 3: glColor3f (legcolor [armnum][head][0] * adder / link,
legcolor [armnum][head][1] * adder / link,
legcolor [armnum][head][2] * adder / link);
break;
}
}
GLfloat surfintense (int segment, int pos, vec3d light) {
float intense;
intense = light.x * snorm [segment][pos][0] +
light.y * snorm [segment][pos][1] +
light.z * snorm [segment][pos][2];
if (intense < 0)
intense = 0.0;
return (intense);
}
GLfloat sphereintense (int segment, int pos, int ysign, vec3d light) {
float intense;
intense = light.x * sphere [segment][pos][0] +
light.y * sphere [segment][pos][1] * (float)ysign +
light.z * sphere [segment][pos][2];
if (intense < 0)
intense = 0.0;
return (intense);
}
GLfloat capintense (vec3d light) {
float intense = light.y;
if (intense < 0)
intense = 0.0;
return (intense);
}
GLvoid drawtorus (int a, int s, vec3d light) {
int i, j;
for (i = 0; i < spts; i++) {
glBegin (GL_QUAD_STRIP);
limbcolor (a, s, 0, surfintense (i, 0, light));
glVertex3f (toroid [i][0][0], toroid [i][0][1], toroid [i][0][2]);
limbcolor (a, s, 1, surfintense (i + 1, 0, light));
glVertex3f (toroid [i + 1][0][0], toroid [i + 1][0][1], toroid [i + 1][0][2]);
for (j = 1; j < qpr; j++) {
limbcolor (a, s, 0, surfintense (i, j, light));
glVertex3f (toroid [i][j][0], toroid [i][j][1], toroid [i][j][2]);
limbcolor (a, s, 1, surfintense (i + 1, j, light));
glVertex3f (toroid [i + 1][j][0], toroid [i + 1][j][1], toroid [i + 1][j][2]);
}
limbcolor (a, s, 0, surfintense (i, 0, light));
glVertex3f (toroid [i][0][0], toroid [i][0][1], toroid [i][0][2]);
limbcolor (a, s, 1, surfintense (i + 1, 0, light));
glVertex3f (toroid [i + 1][0][0], toroid [i + 1][0][1], toroid [i + 1][0][2]);
glEnd ();
}
}
GLvoid drawSphere (int a, int s, vec3d light, int mode) {
int i, j;
for (i = 0; i < (spts - 1); i++) {
glBegin (GL_QUAD_STRIP);
limbcolor (a, s, 0, sphereintense (i, 0, 1, light));
glVertex3f (sphere [i][0][0], sphere [i][0][1], sphere [i][0][2]);
limbcolor (a, s, 1, sphereintense (i + 1, 0, 1, light));
glVertex3f (sphere [i + 1][0][0], sphere [i + 1][0][1], sphere [i + 1][0][2]);
for (j = 1; j < qpr; j++) {
limbcolor (a, s, 0, sphereintense (i, j, 1, light));
glVertex3f (sphere [i][j][0], sphere [i][j][1], sphere [i][j][2]);
limbcolor (a, s, 1, sphereintense (i + 1, j, 1, light));
glVertex3f (sphere [i + 1][j][0], sphere [i + 1][j][1], sphere [i + 1][j][2]);
}
limbcolor (a, s, 0, sphereintense (i, 0, 1, light));
glVertex3f (sphere [i][0][0], sphere [i][0][1], sphere [i][0][2]);
limbcolor (a, s, 1, sphereintense (i + 1, 0, 1, light));
glVertex3f (sphere [i + 1][0][0], sphere [i + 1][0][1], sphere [i + 1][0][2]);
glEnd();
}
glBegin (GL_TRIANGLE_FAN);
limbcolor (a, s, 1, sphereintense (spts, 0, 1, light));
glVertex3f (0.0, 1.0, 0.0);
for (j = 0; j < qpr; j++) {
limbcolor (a, s, 0, sphereintense ((spts - 1), j, 1, light));
glVertex3f (sphere [(spts - 1)][j][0], sphere [(spts - 1)][j][1], sphere [(spts - 1)][j][2]);
}
limbcolor (a, s, 0, sphereintense ((spts - 1), 0, 1, light));
glVertex3f (sphere [(spts - 1)][0][0], sphere [(spts - 1)][0][1], sphere [(spts - 1)][0][2]);
glEnd ();
if (mode == 1)
return;
for (i = 0; i < (spts - 1); i++) {
glBegin (GL_QUAD_STRIP);
limbcolor (a, s, 0, sphereintense (i, 0, -1, light));
glVertex3f (sphere [i][0][0], -sphere [i][0][1], sphere [i][0][2]);
limbcolor (a, s, 1, sphereintense (i + 1, 0, -1, light));
glVertex3f (sphere [i + 1][0][0], -sphere [i + 1][0][1], sphere [i + 1][0][2]);
for (j = 1; j < qpr; j++) {
limbcolor (a, s, 0, sphereintense (i, j, -1, light));
glVertex3f (sphere [i][j][0], -sphere [i][j][1], sphere [i][j][2]);
limbcolor (a, s, 1, sphereintense (i + 1, j, -1, light));
glVertex3f (sphere [i + 1][j][0], -sphere [i + 1][j][1], sphere [i + 1][j][2]);
}
limbcolor (a, s, 0, sphereintense (i, 0, -1, light));
glVertex3f (sphere [i][0][0], -sphere [i][0][1], sphere [i][0][2]);
limbcolor (a, s, 1, sphereintense (i + 1, 0, -1, light));
glVertex3f (sphere [i + 1][0][0], -sphere [i + 1][0][1], sphere [i + 1][0][2]);
glEnd();
}
glBegin (GL_TRIANGLE_FAN);
limbcolor (a, s, 1, sphereintense (spts, 0, -1, light));
glVertex3f (0.0, -1.0, 0.0);
for (j = 0; j < qpr; j++) {
limbcolor (a, s, 0, sphereintense ((spts - 1), j, -1, light));
glVertex3f (sphere [(spts - 1)][j][0], -sphere [(spts - 1)][j][1], sphere [(spts - 1)][j][2]);
}
limbcolor (a, s, 0, sphereintense ((spts - 1), 0, -1, light));
glVertex3f (sphere [(spts - 1)][0][0], -sphere [(spts - 1)][0][1], sphere [(spts - 1)][0][2]);
glEnd ();
}
GLvoid drawCap (int a, int s, vec3d light) {
int j;
glBegin (GL_TRIANGLE_FAN);
limbcolor (a, s, 1, capintense(light));
glVertex3f (0.0, 0.0, 0.0);
limbcolor (a, s, 0, capintense (light));
for (j = 0; j < qpr; j++)
glVertex3f (sphere [0][j][0], sphere [0][j][1], sphere [0][j][2]);
glVertex3f (sphere [0][0][0], sphere [0][0][1], sphere [0][0][2]);
glEnd ();
}
GLvoid mrecurseLinks (int i, GLfloat pitch, int r, int f, int s, int a, vec3d light) {
vec3d tranlight;
vec3d atranlight;
tranlight.x = light.x;
tranlight.y = light.y;
tranlight.z = light.z;
if (f == 0) {
glTranslatef (-majrad, 0.0f, majrad);
glRotatef (-90.0, 0.0f, 1.0f, 0.0f);
tranlight = vecrotate (tranlight, -90, 0, 1, 0);
}
glPushMatrix ();
glRotatef (pitch + (GLfloat)r, 0.0f, 0.0f, 1.0f);
tranlight = vecrotate (tranlight, pitch + r, 0, 0, 1);
if (i == s) {
atranlight.x = tranlight.x;
atranlight.y = tranlight.y;
atranlight.z = tranlight.z;
}
switch (jointstyle) {
case 1: drawAxes ();
break;
case 2: if (f == 1)
break;
if (i == 0)
break;
glPushMatrix ();
glScalef (lard * 2.0, lard * 2.0, lard * 2.0);
glRotatef (90, 1, 0, 0);
tranlight = vecrotate (tranlight, 90, 1, 0, 0);
drawSphere (a, i, tranlight, 0);
glPopMatrix ();
tranlight = vecrotate (tranlight, -90, 1, 0, 0);
break;
}
if (i == 0) {
switch (capstyle) {
case 0:
glRotatef (pitch * 10.0f + (GLfloat)r, 0.0f, 0.0f, 1.0f);
drawTetra (1.0);
break;
case 1:
glScalef (lard, lard, lard);
glRotatef (90, 1, 0, 0);
tranlight = vecrotate (tranlight, 90, 1, 0, 0);
drawSphere (a, 1, tranlight, 1);
break;
case 2:
glScalef (lard, lard, lard);
glRotatef (90, 1, 0, 0);
tranlight = vecrotate (tranlight, 90, 1, 0, 0);
drawCap (a, 1, tranlight);
break;
}
glPopMatrix ();
return;
}
drawtorus (a, i, tranlight);
tranlight = vecrotate (tranlight, 90, 1, 0, 0);
i--;
mrecurseLinks (i, -pitch, r * 2, 0, s, a, tranlight);
if (i == s) {
// tranlight = vecrotate (tranlight, 90, 1, 0, 0);
// atranlight = vecrotate (atranlight, 90, 0, 0, 1);
// glPushMatrix ();
glRotatef (180.0f, 0.0f, 0.0f, 1.0f);
drawtorus (a + 5, i, atranlight);
mrecurseLinks (i - 1, -pitch, r * 2, 0, -1, a + 5, atranlight);
// glPopMatrix ();
}
glPopMatrix ();
}
GLvoid drawSpinCenter (float pitch) {
glEnable (GL_BLEND);
glRotatef (pitch * 5, 0.0f, 0.0f, 1.0f);
glRotatef (-pitch * 5, 0.0f, 1.0f, 0.0f);
glRotatef (pitch * 5, 1.0f, 0.0f, 0.0f);
glScalef (2.0, 2.0, 2.0);
drawTetra (0.7);
glRotatef (pitch * 2, 0.0f, 0.0f, 1.0f);
glRotatef (-pitch * 5, 1.0f, 0.0f, 0.0f);
glScalef (1.5, 1.5, 1.5);
drawTetra (0.5);
glDisable (GL_BLEND);
}
GLvoid drawPulseBlob (float pitch, vec3d light) {
float sfa = 0.3 * sin (pitch / 40) + 1.2;
float sfb = 0.4 * cos (pitch / 44 + 1) + 1.2;
glPushMatrix ();
glRotatef (-45, 0.0, 0.0, 1.0);
glRotatef (45, 1.0, 0.0, 0.0);
light = vecrotate (light, -45, 0, 0, 1);
light = vecrotate (light, 45, 1, 0, 0);
glScalef (sfa, sfb, sfa);
drawSphere (8, 1, light, 0);
glPopMatrix ();
}
GLvoid drawScene(GLvoid)
{
static float pitch = 0.0;
int i;
vec3d lightsource;
lightsource.x = masterlight.x;
lightsource.y = masterlight.y;
lightsource.z = masterlight.z;
if (bufstyle)
glClear(GL_DEPTH_BUFFER_BIT);
else
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix (); // master view
glTranslatef (0.5 * sin (pitch / 20), 0.0, -20.0f + 3.0 * cos (pitch/20));
for (i = 0; i < noodlecount; i++)
mrecurseLinks (armlengths [i], rspeeds [i] * pitch + i * 200,
i * 8 + 10, 1, -1, i, lightsource);
switch (centerstyle) {
case 0: drawSpinCenter (pitch);
break;
case 1: drawPulseBlob (pitch, masterlight);
break;
}
glPopMatrix (); // pop master view
glFinish();
SwapBuffers(ghDC);
framecount++;
pitch += PITCH_SPEED;
if (pitch > 10000000.0) {
pitch -= 10000000.0;
}
if (pitch < 0) {
pitch += 10000000.0;
}
if (colorcycle) {
cycleaccum++;
cyclepitch += cyclespeed;
if (cycleaccum == 10) {
cycleaccum = 0;
cyclecolors (cyclepitch);
}
}
}